﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.ComponentModel;
using System.Drawing;
using System.Runtime.InteropServices;

using MyLibrary.UI.HighLight;


/*
 * 下一步改进计划:
 * 优化查词的算法
 * 支持外部导入高亮关键字列表
 * 编写插件接口
 */

namespace MyLibrary.UI.HighLight
{
    public class HighLightTextBox : RichTextBox
    {
        private Container components = null;
        private const int WM_SETREDRAW = 0xB;
        private Parser parser = null;

        [DllImport("user32")]
        private static extern int SendMessage(IntPtr hwnd, int wMsg, int wParam, IntPtr IParam);
        

        public HighLightTextBox()
        {
            InitializeComponent();
            //base.WordWrap = false;
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (components != null)
                    components.Dispose();
            }
            base.Dispose(disposing);
        }

        private void InitializeComponent()
        {
            this.Name = "HightListTextBox";
        }

        protected override void OnTextChanged(EventArgs e)
        {
            if (this.parser == null) return;

            //如果文本框中的字符串不为空
            if (!String.IsNullOrEmpty(base.Text))
            {
                int selectStart = base.SelectionStart;
                int line = base.GetLineFromCharIndex(selectStart);
                //int line = base.Lines.Length;
                string lineString = String.Empty;
                if (line == 0)
                    lineString = base.Lines[line];
                else
                    lineString = base.Lines[line - 1];
                int lineStart = 0;
                for (int i = 0; i < line; i++)
                    lineStart += base.Lines[i].Length + 1;
                SendMessage(base.Handle, WM_SETREDRAW, 0, IntPtr.Zero);

                base.SelectionStart = lineStart;
                base.SelectionLength = lineString.Length;
                base.SelectionColor = Color.Black;
                base.SelectionStart = selectStart;
                base.SelectionLength = 0;

                string[] words = lineString.Split(new char[] { ' ', '(', ',' }, StringSplitOptions.RemoveEmptyEntries);
                Color wordColor = Color.Black;
                for(int i=0;i<words.Length;i++)
                {
                    if(parser.IsKeyWord(words[i], out wordColor))
                    {
                        int length = 0;
                        for (int j = 0; j < i; j++)
                            length += words[j].Length;
                        length += i;
                        int index = lineString.IndexOf(words[i], length);

                        base.SelectionStart = lineStart + index;
                        base.SelectionLength = words[i].Length;
                        base.SelectionColor = wordColor;
                        base.SelectionStart = selectStart;
                        base.SelectionLength = 0;
                        base.SelectionColor = Color.Black;
                    }
                }
                SendMessage(base.Handle, WM_SETREDRAW, 1, IntPtr.Zero);
                base.Refresh();
            }
            base.OnTextChanged(e);
        }

        public new bool WordWrap
        {
            get { return base.WordWrap; }
            set { base.WordWrap = value; }
        }

        private LanguageType language = LanguageType.CSharp;

        [Category("Action"), Editor(typeof(LanguageType), typeof(Enum)), Browsable(true), Description("设置高亮语法")]
        public LanguageType Language
        {
            get { return language; }
            set 
            {
                language = value; 
                if(parser == null)
                    parser = Parser.CreateParserInstance(this.language);
            }
        }
    }
}
